package com.ruoyi.business.rtsp.news;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.WebAsyncTask;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: Jacky
 * @Date: 2025-7-7 9:41
 * @Description: com.ruoyi.business.rtsp.news
 * @version: 1.0
 */
@RestController
public class VideoController {
    @Autowired
    private VideoStreamService videoStreamService;

    @GetMapping(value = "/video-stream", produces = "video/x-flv")
    @CrossOrigin(origins = "*")
    public WebAsyncTask<Void> streamVideo(@RequestParam String rtspUrl,
                                          //HttpServletRequest request,
                                          HttpServletResponse response) {
        response.setHeader("Connection", "keep-alive");
        response.setHeader("Cache-Control", "no-cache");
        response.setContentType("video/x-flv");


        //System.out.println("debug");
        // 设置异步请求超时时间（单位：毫秒）
        //AsyncContext asyncContext = request.startAsync();
        //asyncContext.setTimeout(600000); // 0表示永不超时，或设置为足够大的值如600000(10分钟)


        // 设置异步任务超时为1小时（根据需求调整）
        long timeout = TimeUnit.HOURS.toMillis(1);
        Callable<Void> videoStreamCallable = () -> {
            boolean isError = false; // 错误状态标志
            FFmpegFrameGrabber grabber = null;
            FFmpegFrameRecorder recorder = null;

            try (OutputStream outputStream = response.getOutputStream()) {
                grabber = new FFmpegFrameGrabber(rtspUrl);
                /*grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
                grabber.setFrameRate(25); // 设置合理的帧率，最后加的测试
                grabber.setVideoBitrate(1500000); // 设置比特率，最后加的测试
                grabber.setOption("fflags", "discardcorrupt");
                grabber.setOption("flags", "low_delay");
                grabber.setOption("stimeout", "20000000");  // 20秒超时
                grabber.setOption("max_delay", "2000000"); // 最大延迟2秒
                grabber.setOption("reorder_queue_size", "10");//最后加的测试
                //grabber.setOption("rtsp_transport", "tcp"); // 强制TCP传输
                grabber.setOption("reconnect", "1"); // 启用自动重连
                grabber.setOption("reconnect_at_eof", "1"); // EOF时重连
                grabber.setOption("reconnect_streamed", "1"); // 流中断重连
                grabber.setOption("reconnect_delay_max", "30"); // 最大重连延迟30秒
                grabber.setOption("rtsp_flags", "prefer_tcp"); // Prefer TCP but fallback to UDP
                grabber.setOption("analyzeduration", "1000000"); // Increase analyze duration
                grabber.setOption("probesize", "5000000");  // 超时5秒*/

                grabber.setOption("rtsp_transport", "tcp"); // 强制TCP确保稳定
                grabber.setOption("muxrate", "5000000"); // 匹配比特率

                // 抓取器配置优化
                grabber.setVideoBitrate(5000000); // 输入流比特率设置
                grabber.setFrameRate(30); // 与输出帧率一致
                grabber.setImageWidth(1920); // 明确设置分辨率
                grabber.setImageHeight(1080);
                grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);

                // 高级解码参数
                grabber.setOption("threads", "4"); // 使用多线程解码
                grabber.setOption("flags", "low_delay");
                grabber.setOption("fflags", "nobuffer");
                grabber.setOption("analyzeduration", "1000000"); // 增加分析时长
                grabber.setOption("probesize", "10000000"); // 增加探测数据量

                grabber.setOption("stimeout", "20000000");  // 20秒超时
                grabber.setOption("max_delay", "2000000"); // 最大延迟2秒
                grabber.setOption("reorder_queue_size", "10");//最后加的测试

                grabber.setOption("reconnect", "1"); // 启用自动重连
                grabber.setOption("reconnect_at_eof", "1"); // EOF时重连
                grabber.setOption("reconnect_streamed", "1"); // 流中断重连
                grabber.setOption("reconnect_delay_max", "30"); // 最大重连延迟30秒

                // 硬件加速支持(如果可用)
                grabber.setVideoOption("hwaccel", "auto");
                grabber.setVideoOption("hwaccel_device", "0");

                // 增加网络缓冲
                grabber.setVideoOption("tune", "zerolatency");
                grabber.setVideoOption("bufsize", "6000k"); // 6MB缓冲区
                grabber.setVideoOption("maxrate", "4000000"); // 最大比特率
                grabber.setVideoOption("minrate", "2000000"); // 最小比特率
                //grabber.setVideoOption("bufsize", "5000k"); // 输入缓冲区5MB

                try {
                    grabber.start();
                } catch (Exception e) {
                    isError = true;
                    throw new IOException("Failed to connect to RTSP stream: " + rtspUrl, e);
                }
                //grabber.start();

                recorder = new FFmpegFrameRecorder(
                        outputStream,
                        grabber.getImageWidth(),
                        grabber.getImageHeight(),
                        grabber.getAudioChannels()
                );
                recorder.setFormat("flv");
                /*recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
                recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
                recorder.setVideoOption("tune", "zerolatency");
                recorder.setVideoOption("preset", "ultrafast");
                recorder.setVideoOption("crf", "23");*/

                // 修改FFmpeg录制器参数
                recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
                recorder.setVideoBitrate(3000000); // 比特率提升到3Mbps (原1500000)
                recorder.setVideoOption("preset", "medium"); // 改为medium平衡画质与延迟
                recorder.setVideoOption("profile", "high"); // 使用High Profile
                recorder.setVideoOption("tune", "film"); // 针对高质量视频源优化
                recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
                recorder.setVideoQuality(25); // 质量系数(0-51，值越小质量越高)
                recorder.setFrameRate(30); // 帧率提升到30fps (原25)

                // 关键帧间隔优化
                recorder.setGopSize(60); // 每60帧一个关键帧(2秒)
                recorder.setVideoOption("x264opts", "no-scenecut=1:rc-lookahead=30");

                // 提升编码参数
                recorder.setVideoOption("crf", "18"); // CRF值降低(18-28，原23)
                recorder.setVideoOption("aq-mode", "2"); // 自适应量化模式
                recorder.setVideoOption("aq-strength", "0.8"); // 自适应量化强度

                recorder.start();

                Frame frame;
                //while ((frame = grabber.grab()) != null) {
                while (!Thread.currentThread().isInterrupted() && (frame = grabber.grab()) != null) {
                    /*if (Thread.currentThread().isInterrupted()) {
                        break; // 响应超时中断
                    }*/
                    recorder.record(frame);
                    outputStream.flush();
                }
            } catch (Exception e) {
                // 忽略客户端断开连接的错误
                /*if (!e.getMessage().contains("Broken pipe") &&
                        !e.getMessage().contains("Connection reset")) {
                    throw e;
                }*/
                if (!isClientDisconnected(e)) {
                    isError = true;
                    throw e;
                }
            } finally {
                // 按相反顺序清理资源
                if (recorder != null) {
                    try {
                        if (!isError) recorder.stop();
                        recorder.close();
                    } catch (Exception ignored) {}
                }
                if (grabber != null) {
                    try {
                        if (!isError) grabber.stop();
                        grabber.close();
                    } catch (Exception ignored) {}
                }
            }
            return null;
        };

        WebAsyncTask<Void> asyncTask = new WebAsyncTask<>(timeout, videoStreamCallable);
        /*asyncTask.onTimeout(() -> {
            // 超时处理（自动中断Callable）
            return null;
        });*/
        asyncTask.onTimeout(() -> null);

        return asyncTask;
    }

    private boolean isClientDisconnected(Exception e) {
        if (e == null || e.getMessage() == null) return false;
        String msg = e.getMessage().toLowerCase();
        return msg.contains("broken pipe") ||
                msg.contains("connection reset") ||
                msg.contains("outputstream closed");
    }
}
